package com.loozb.thread5.disruptor;

import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import com.loozb.thread4.queue.*;

import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 1.定义事件：定义PCData，用来进行交换的数据类型
 * 2.定义事件工程：定义PCDataFactory
 * 3.定义事件处理的具体实现 Consumer和Consumer2
 *
 *
 * @author 龙召碧
 * @create 2018-02-09 13:01
 **/
public class Main {
    public static void main(String[] args) throws Exception {
        //创建线程池
        Executor executor = Executors.newCachedThreadPool();

        //创建数据工厂
        PCDataFactory factory = new PCDataFactory();

        int bufferSize = 1024;


        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger index = new AtomicInteger(1);
            @Override
            public Thread newThread(Runnable r) {
                return new Thread((ThreadGroup) null, r, "disruptor-thread-" + index.getAndIncrement());
            }
        };

        /**
         * 等待策略
         * BlockingWaitStrategy 是最低效的策略，但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现；
         * SleepingWaitStrategy 的性能表现跟 BlockingWaitStrategy 差不多，对 CPU 的消耗也类似，但其对生产者线程的影响最小，适合用于异步日志类似的场景；
         * YieldingWaitStrategy 的性能是最好的，适合用于低延迟的系统。在要求极高性能且事件处理线数小于 CPU 逻辑核心数的场景中，推荐使用此策略；例如，CPU开启超线程的特性。
         */
        Disruptor<PCData> disruptor = new Disruptor<PCData>(factory,
                bufferSize,
                threadFactory,
                ProducerType.MULTI,
                new BlockingWaitStrategy());
        disruptor.handleEventsWith(new Consumer());
        disruptor.handleEventsWith(new Consumer2());
        //创建消费者线程池,可以有多个消费者，分开创建，则需要多个业务时
//        disruptor.handleEventsWithWorkerPool(
//                new Consumer()
//        );
//        disruptor.handleEventsWithWorkerPool(
//                new Consumer2()
//        );

        //启动线程
        disruptor.start();

        //创建disruptor缓冲区,用于存放数据
        RingBuffer<PCData> ringBuffer = disruptor.getRingBuffer();
        //将缓冲区赋值给生产
        Producer producer = new Producer(ringBuffer);

        //作数据的字节（byte）形式,产生的内存开销是在JVM中的
        ByteBuffer bb = ByteBuffer.allocate(8);
//        for (long l = 0; l < 2; l++) {
            bb.putLong(0, 1);
            producer.pushData(bb);//写入缓冲区
            Thread.sleep(100);
            System.out.println("add data" + 1);
//        }
        disruptor.shutdown();
    }
}
